﻿package com.designoutput.ui.controls
{
	import com.designoutput.event.NumberEvent;
	
	import flash.events.*;
	import flash.text.*;
	import flash.ui.Keyboard;

	[Event(name="valueChange", type="com.designoutput.event.NumberEvent")]
	public class NumberInput extends TextField
	{
		private var _isDecimal:Boolean;
		private var _minValue:Number;
		private var _maxValue:Number;
		private var _value:Number = 0;
		private var _changeOnFocusOut:Boolean = false;

		public function NumberInput(width:int, txt:Number, min:Number=0, max:Number=100, decimal:Boolean=false, lateChangeEvent:Boolean = false)
		{
			_minValue = min;
			_maxValue = max;
			_isDecimal = decimal;
			_changeOnFocusOut = lateChangeEvent;
			
			defaultTextFormat = new TextFormat("Verdana, Helvetica, San-serif", 10, 0, null, null, null, null, null, "right");
			type = TextFieldType.INPUT;
			maxChars = max.toString().length;
			
			if (min < 0)
			{
				(this.maxChars + 1);
			}
			if (decimal)
			{
				this.maxChars=this.maxChars + 2;
			}
			this.background=true;
			this.backgroundColor=16777215;
			this.border=true;
			this.borderColor=9474192;
			this.height=16;
			this.width=width;
			this.restrict="0-9 +-.";
			if (!decimal)
			{
				this.text=txt.toString();
			}
			else
			{
				this.text=txt.toString() + ".0";
			}
			
			this.addEventListener(KeyboardEvent.KEY_UP, this.keyUp);
			this.addEventListener(FocusEvent.FOCUS_IN, this.focusInHandler);
			this.addEventListener(FocusEvent.FOCUS_OUT, this.focusOutHandler);
		}

		/**
		 * Just prevent keyborad event when focus the input. This application will do something when press arrow key and backspace etc.
		 * @param evt
		 *
		 */
		private function inputKeyDown(evt:KeyboardEvent):void
		{
			evt.stopPropagation();
		}

		private function focusInHandler(event:FocusEvent):void
		{
			this.stage.addEventListener(KeyboardEvent.KEY_DOWN, inputKeyDown, true);
		}

		private function focusOutHandler(event:FocusEvent):void
		{
			this.stage.removeEventListener(KeyboardEvent.KEY_DOWN, inputKeyDown, true);

			if(_changeOnFocusOut){
				updateValueFromText();
				updateTextFromValue();
				dispatchEvent(new NumberEvent(NumberEvent.VALUE_CHANGE, _value));
			}
		}

		private function keyUp(event:KeyboardEvent):void
		{
			if(!_changeOnFocusOut){
				updateValueFromText();
				dispatchEvent(new NumberEvent(NumberEvent.VALUE_CHANGE, _value));
			} else if(event.keyCode == Keyboard.ENTER){
				updateValueFromText();
				updateTextFromValue();
				dispatchEvent(new NumberEvent(NumberEvent.VALUE_CHANGE, _value));
			}
		}

		override public function set text(value:String):void {
			super.text = value;
			updateValueFromText();
		}
		
		public function get value():Number {
			return _value;
		}
		
		public function set value(v:Number):void {
			_value = v;
			
			restrictValue();
			
			updateTextFromValue();
		}
		
		private function updateValueFromText():void {
			_value = Number(text);
			restrictValue();
		}
		
		private function updateTextFromValue():void {
			if (isNaN(_value))
				text = "";
			
			if (_value.toString().indexOf(".") != -1 || !_isDecimal)
				text= _value.toString();
			else
				text = _value.toString() + ".0";
		}
		
		private function restrictValue():void {
			if (isNaN(_value))
				_value=0;
			
			if (!_isDecimal)
				_value=Math.round(_value);
			
			if (_value < _minValue)
				_value = _minValue;
				
			else if (_value > _maxValue)
				_value = _maxValue;
		}
	}
}
